package com.lhl.jwt.security.providers;

import com.lhl.jwt.exception.JwtException;
import com.lhl.jwt.exception.JwtExpireException;
import com.lhl.jwt.service.JwtUserDetailsService;
import com.lhl.jwt.token.JwtAuthenticationToken;
import com.lhl.jwt.utils.JwtConstant;
import com.nimbusds.jwt.SignedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

import java.text.ParseException;
import java.util.Date;


/**
 * jwt认证主要逻辑
 * @author zhangyf
 * @date 2019年8月16日
 */
@Slf4j
public class JwtAuthenticationProvider implements AuthenticationProvider, InitializingBean {

	private final JwtUserDetailsService userDetailsService;

	public JwtAuthenticationProvider(JwtUserDetailsService userDetailsService) {
		this.userDetailsService = userDetailsService;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		Assert.notNull(this.userDetailsService, "A UserDetailsService must be set");
	}
	
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		SignedJWT jwt = ((JwtAuthenticationToken) authentication).getToken();
		Assert.notNull(jwt, JwtConstant.TOKEN_NOT_EMPTY);
		log.debug("jwt=={}",jwt.getParsedString());
		try {
            //验证token是否过期
			if(jwt.getJWTClaimsSet().getExpirationTime().before(new Date())){
				throw new JwtExpireException(JwtConstant.TOKEN_EXPIRE);
			}
			//从缓存或数据库中获取user对象
			String username = jwt.getJWTClaimsSet().getSubject();

			UserDetails user = userDetailsService.loadUserByUsername(username);
			if (user == null) {
				return null;
			}
//			String salt = getSalt(username);
//			JwtUtils.checkJWT(jwt.getParsedString(), salt, username);
			JwtAuthenticationToken token = new JwtAuthenticationToken(user, jwt, user.getAuthorities());
			return token;
		} catch (ParseException e) {
			throw new JwtException(JwtConstant.TOKEN_VERIFY_ERROR);
		}
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return authentication.isAssignableFrom(JwtAuthenticationToken.class);
	}

	/*protected String getSalt(String username) {
		String salt = userDetailsService.getSalt(username);
		if (StringUtils.isBlank(salt)) {
			salt = JwtUtils.TOKEN_SECRET;
		}
		return salt;
	}*/
	
}
